package br.com.algarmidia.controllers;

import java.util.List;

import org.springframework.util.CollectionUtils;

import br.com.algarmidia.models.User;
import br.com.algarmidia.repositories.UserRepository;
import br.com.algarmidia.services.UserService;
import br.com.caelum.vraptor.Delete;
import br.com.caelum.vraptor.Get;
import br.com.caelum.vraptor.Post;
import br.com.caelum.vraptor.Put;
import br.com.caelum.vraptor.Resource;
import br.com.caelum.vraptor.Result;
import br.com.caelum.vraptor.Validator;
import br.com.caelum.vraptor.validator.ValidationMessage;
import br.com.caelum.vraptor.view.Results;

//Esta anotação informa ao servidor de aplicação que a classe é um Controller do VRaptor.
//Todos os seus métodos públicos terão por padrão um link que leva à sua execução
@Resource
public class UserController {

	private final Result result;
	private final UserRepository repository;
	private final UserService userService;
	private final Validator validator;
	
	//Para injetar um componente no VRaptor, coloque-o como parâmetro no construtor da classe 
	//Um componente é uma classe anotada como as annotations @Component (vraptor), @Resource (vraptor) ou @Service (spring)

	/**
	 * Controller da classe User, com os componentes Result, UserRepository, UserService e Validator injetados
	 * @param result
	 * @param repository
	 * @param userService
	 * @param validator
	 */
	UserController(Result result, UserRepository repository, UserService userService, Validator validator) {
		this.result = result;
		this.repository = repository;
		this.userService = userService;
		this.validator = validator;
	}

	/**
	 * Chamada REST ao método index() via HTTP-GET, que busca todos os usuários cadastrados
	 * @return Retorna todos os usuários cadastrados
	 */
	@Get("/users")
	public List<User> index() {
		return repository.findAll();
	}

	/**
	 * Chamada REST ao método create(User) via HTTP-POST, que visa cadastrar um novo usuário
	 * @param user Usuário a ser criado
	 */
	@Post("/users")
	public void create(User user) {
		List<ValidationMessage> validationMessages = user.validate(); 
		if (!CollectionUtils.isEmpty(validationMessages)) {
			validator.addAll(validationMessages);
		}
		validator.onErrorUsePageOf(this).newUser();
		repository.create(user);
		result.redirectTo(this).index();
	}

	/**
	 * Chamada REST ao método newUser() via HTTP-GET, que retorna um usuário sem dados
	 * @return Usuário em branco
	 */
	@Get("/users/new")
	public User newUser() {
		return new User();
	}

	/**
	 * Chamada REST ao método update(User) via HTTP-PUT, que atualiza um usuário no banco
	 * @param user Usuário a ser atualizado
	 */
	@Put("/users")
	public void update(User user) {
		if (user.getId() == null) {
			validator.add(new ValidationMessage("user.id.empty", "error"));
		}
		List<ValidationMessage> validationMessages = user.validate();
		if (!CollectionUtils.isEmpty(validationMessages)) {
			validator.addAll(validationMessages);
		}
		validator.onErrorUsePageOf(this).edit(user);
		repository.update(user);
		result.redirectTo(this).index();
	}

	/**
	 * Chamada REST ao método edit(User) via HTTP-GET, que busca os dados do usuário para edição
	 * @param user Dados do usuário a ser editado
	 * @return Retorna o usuário a ser editado
	 */
	@Get("/users/{user.id}/edit")
	public User edit(User user) {
		if (user.getId() == null) {
			validator.add(new ValidationMessage("user.id.empty", "error"));
		}
		validator.onErrorUsePageOf(this).edit(user);
		return repository.find(user.getId());
	}

	/**
	 * Chamada REST ao método show(User) via HTTP-GET, que busca os dados do usuário para visualização
	 * @param user Dados do usuário a ser visualizado
	 * @return Retorna o usuário a ser visualizado
	 */
	@Get("/users/{user.id}")
	public User show(User user) {
		if (user.getId() == null) {
			validator.add(new ValidationMessage("user.id.empty", "error"));
		}
		validator.onErrorUsePageOf(this).edit(user);
		return repository.find(user.getId());
	}

	/**
	 * Chamada REST ao método destroy(User) via HTTP-DELETE, que visa remover o usuário do banco
	 * @param user Usuário a ser removido
	 */
	@Delete("/users/{user.id}")
	public void destroy(User user) {
		if (user.getId() == null) {
			validator.add(new ValidationMessage("user.id.empty", "error"));
		}
		validator.onErrorUsePageOf(this).edit(user);
		userService.destroy(user);
		result.redirectTo(this).index();  
	}

	public void test() {
		User user = new User(1L, "Usuario Teste", "Password Teste", "email@teste.com.br");
		result.use(Results.json()).from(user).serialize();
	}
}